package com.ygqh.baby.service.impl;

import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.tuple.Text;
import com.foxinmy.weixin4j.util.StringUtil;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.ygqh.baby.ao.*;
import com.ygqh.baby.constant.Constant;
import com.ygqh.baby.exception.YgException;
import com.ygqh.baby.handler.SaveMainOrderHandler;
import com.ygqh.baby.mapper.YgUserBargainMapper;
import com.ygqh.baby.model.*;
import com.ygqh.baby.po.*;
import com.ygqh.baby.po.YgUserBargainExample.Criteria;
import com.ygqh.baby.service.*;
import com.ygqh.baby.utils.DateConvertUtils;
import com.ygqh.baby.utils.SplitPriceUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author admin
 */
@Service
public class YgUserBargainServiceImpl implements YgUserBargainService {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private YgUserBargainMapper ygUserBargainMapper;
    @Autowired
    private YgBargainService ygBargainService;
    @Autowired
    private YgUserBargainDetailService ygUserBargainDetailService;
    @Autowired
    private YgProductService ygProductService;
    @Autowired
    private YgShoppingCarService ygShoppingCarService;
    @Autowired
    private YgStockService ygStockService;
    @Autowired
    private YgUserBalanceService ygUserBalanceService;
    @Autowired
    private YgSkuService ygSkuService;
    @Autowired
    private WxMpMessageService wxMpMessageService;
    @Autowired
    private YgUserService ygUserService;

    @Autowired
    private WxAttentionService wxAttentionService;
    @Autowired
    private WxSmallMessageService wxSmallMessageService;
    @Autowired
    private YgUserAuthsService ygUserAuthsService;

    private ExecutorService executorService;

    @PostConstruct
    public void init() {
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
                .setNameFormat("userBargain").build();
        executorService = new ThreadPoolExecutor(3, 6,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
    }

    @Override
    public List<YgUserBargain> find() {
        YgUserBargainExample example = new YgUserBargainExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
        return ygUserBargainMapper.selectByExample(example);
    }

    @Override
    public int findCount() {
        YgUserBargainExample example = new YgUserBargainExample();
        example.createCriteria().andStatusEqualTo(DataStatus.Valid.name());
        return ygUserBargainMapper.countByExample(example);
    }

    @Override
    public YgUserBargain findById(Long id) {
        return ygUserBargainMapper.selectByPrimaryKey(id);
    }

    @Override
    public int save(YgUserBargain ygUserBargain) {
        return ygUserBargainMapper.insertSelective(ygUserBargain);
    }

    @Override
    public int update(YgUserBargain ygUserBargain) {
        return ygUserBargainMapper.updateByPrimaryKeySelective(ygUserBargain);
    }

    @Override
    public ResultSet<YgUserBargain> search(QueryInfo queryInfo, Long productId, Long bargainId, Long userId, String q, String platformNo) {
        List<YgUserBargain> list = ygUserBargainMapper.selectSuper(queryInfo, productId, bargainId, userId, q, platformNo);
        int count = ygUserBargainMapper.countSuper(productId, bargainId, userId, q, platformNo);
        ResultSet<YgUserBargain> resultSet = new ResultSet<YgUserBargain>(count, list);
        return resultSet;
    }

    @Override
    public ResultSet<YgUserBargain> search(QueryInfo queryInfo, Long userBargainId, String userName, String productName, Date startDate, Date endDate,
                                           JobStatus jobStatus, String q) {
        String status = jobStatus == null ? null : jobStatus.name();
        List<YgUserBargain> list = ygUserBargainMapper.selectUserBargainSuper(queryInfo, userBargainId, userName, productName, startDate, endDate, status, q);
        int count = ygUserBargainMapper.countUserBargainSuper(userBargainId, userName, productName, startDate, endDate, status, q);
        ResultSet<YgUserBargain> resultSet = new ResultSet<YgUserBargain>(count, list);
        return resultSet;
    }

    ;

    @Override
    public int deleteSoft(Long[] ids) {
        Assert.notEmpty(ids);
        YgUserBargainExample example = new YgUserBargainExample();
        example.createCriteria().andIdIn(Arrays.asList(ids));
        YgUserBargain record = new YgUserBargain();
        record.setStatus(DataStatus.Delete);

        return ygUserBargainMapper.updateByExampleSelective(record, example);
    }

    @Override
    public int deleteSoft(Long id) {
        return this.deleteSoft(new Long[]{id});
    }

    @Override
    public int saveOrUpdate(YgUserBargain ygUserBargain) {
        int r = 0;
        if (ygUserBargain.getId() != null) {
            r = this.update(ygUserBargain);
        } else {
            r = this.save(ygUserBargain);
        }
        return r;
    }

    @Override
    public Boolean existUserBargain(Long userId, Long productId, Long bargainId) {
        Boolean exist = false;
        YgUserBargainExample example = new YgUserBargainExample();
        example.createCriteria().andUserIdEqualTo(userId).andBargainIdEqualTo(bargainId).andProductIdEqualTo(productId)
                .andFinishTimeGreaterThanOrEqualTo(new Date()).andStatusEqualTo(DataStatus.Valid.name());
        int i = ygUserBargainMapper.countByExample(example);
        if (i > 0) {
            exist = true;
        }
        return exist;
    }

    @Override
    public Message addUserBargain(Long productId, Long userAddressId, Long userId, String platformNo, Long skuId) {

        // 校验砍价活动
        ProductBargainData productBargainData = ygBargainService.findProductBargainData(productId, null, platformNo);
        if (productBargainData == null || !PromotionStatus.Running.equals(productBargainData.getPromotionStatus())) {
            return Message.error("亲，您来晚了，活动已结束。", null);
        }
        // 校验是否重复发起
        YgUserBargain userBargain = this.findUserBargain(userId, productBargainData.getProductId(), productBargainData.getBargainId());
        if (userBargain == null) {
            Message message = checkForAdd(productBargainData, userId);
            if (!Message.Type.success.equals(message.getType())) {
                return message;
            }
            YgProduct product = ygProductService.findById(productId);
            Date currentDate = new Date();
            Date finishTime = DateConvertUtils.addMinute(currentDate, productBargainData.getCountDown() * 60);

            userBargain = new YgUserBargain(userId, productId, product.getProductSalePrice(), productBargainData.getBargainId(), productBargainData.getTargetPrice(),
                    productBargainData.getRandomCutCount(), new BigDecimal("0.00"), finishTime, JobStatus.Running, currentDate, skuId);
            userBargain.setPlatformNo(platformNo);
            userBargain.setUserAddressId(userAddressId);
            this.save(userBargain);
            this.addQuartzJob(userBargain.getId(), userBargain.getFinishTime());
        }
        return Message.success(userBargain.getId());

    }

    private Message checkForAdd(ProductBargainData productBargainData, Long userId) {
        if (productBargainData == null || !PromotionStatus.Running.equals(productBargainData.getPromotionStatus())) {
            return Message.error("亲，您来晚了，活动已结束。", null);
        }
        //获取当前活动，用户参与的有效数量
        Long validCount = countOfValid(userId, productBargainData.getBargainId());
        /**
         * buycount=0 : 不限制购买次数
         */
        if (productBargainData.getBuyCount() > 0 && validCount.intValue() >= productBargainData.getBuyCount()) {
            return Message.error("亲，您已参加了该活动，不要贪心哦。", productBargainData.getProductId());
        }
        /**
         * 校验库存
         */
        if (productBargainData.getRealStock() && productBargainData.getStockQuantity().compareTo(0L) > 0) {
            int completedCount = this.findCompletedCount(productBargainData.getBargainId(), productBargainData.getProductId(), null);
            if (productBargainData.getStockQuantity() - completedCount <= 0) {
                return Message.error("亲，您来晚了，商品已被抢光。", productBargainData.getProductId());
            }
        }
        return Message.success(null);

    }

    private Long countOfValid(Long userId, Long bargainId) {
        List<YgUserBargain> userBargainList = findUserBargainList(userId, bargainId);
        if (CollectionUtils.isEmpty(userBargainList)) {
            return 0L;
        }
        return userBargainList.stream().filter(b -> !JobStatus.Finish.equals(b.getBargainStatus())).count();

    }

    private List<YgUserBargain> findUserBargainList(Long userId, Long bargainId) {
        YgUserBargainExample example = new YgUserBargainExample();
        example.createCriteria().andUserIdEqualTo(userId).andBargainIdEqualTo(bargainId).andStatusEqualTo(DataStatus.Valid.name());
        return ygUserBargainMapper.selectByExample(example);
    }

    @Autowired
    private ScheduleJobService scheduleJobService;

    private void addQuartzJob(Long userBargainId, Date finishTime) {

        executorService.execute(() -> {
            Map<String, Object> param = new HashMap<>();
            param.put("userBargainId", userBargainId);
            scheduleJobService.addJob(YgQuartzJob.BargainInvitation, userBargainId.toString(), DateConvertUtils.addMinute(finishTime, -60),
                    param, "addUserBargain");
        });

    }

    @Override
    public List<YgUserBargain> findUserBargainList(QueryInfo queryInfo, Long productId, Long bargainId, Long userId, String platformNo) {

        return ygUserBargainMapper.selectSuper(queryInfo, productId, bargainId, userId, null, platformNo);
    }

    @Autowired
    private YgOrderService ygOrderService;

    @Override
    public UserBargainInfo findUserBargainInfo(Long userBargainId) {
        UserBargainInfo userBargainInfo = ygUserBargainMapper.selectUserBargainInfo(userBargainId);
        if (BargainGenerationMode.Order.equals(userBargainInfo.getGenerationMode())
                && JobStatus.Complete.equals(userBargainInfo.getBargainStatus())) {
            YgOrder order = ygOrderService.findByReleateId(userBargainId, OrderType.KanJia);
            if (order != null) {
                userBargainInfo.setOrderId(order.getOrderId());
            }
        }
        return userBargainInfo;
    }

    @Override
    public int updateCutPrice(BigDecimal preCutPrice, BigDecimal thisCutPrice, Long lastCutCount, Long userBargainId) {
        return ygUserBargainMapper.updateCutPrice(preCutPrice, thisCutPrice, lastCutCount, userBargainId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Message cutPrice(Long userId, String openId, String headUrl, String nickName, Long userBargainId) {
        YgUserBargain bargain = this.findById(userBargainId);
        Message message = checkCutPrice(bargain, userId, openId);
        if (!Message.Type.success.equals(message.getType())) {
            return message;
        }
        // 获取本次砍价金额
        BigDecimal cutPrice = this.getThisCutPrice(bargain);

        YgUserBargainDetail bargainDetail = null;
        int i = this.updateCutPrice(bargain.getCutPrice(), bargain.getCutPrice().add(cutPrice), bargain.getLastCutCount(), userBargainId);
        if (i > 0) {
            bargainDetail = ygUserBargainDetailService.addUserBargainDetail(userId, openId, headUrl, nickName, userBargainId, cutPrice);
        }
        autoCompleteUserBargain(userBargainId, false);
        return Message.success(bargainDetail);
    }

    private Message checkCutPrice(YgUserBargain bargain, Long cutUserId, String openId) {
        if (bargain.getFinishTime().before(new Date())) {
            return Message.error("不好意思，您来晚啦，您好友的砍价结束。", null);
        }
        // 校验是否重复砍价
        Boolean alreadyCut = ygUserBargainDetailService.alreadyCut(openId, bargain.getId());
        if (alreadyCut) {
            return Message.error("请不要重复砍价。", null);
        }

        if (bargain.getLastCutCount() == 0 || bargain.getBargainStatus().equals(JobStatus.Complete)) {
            return Message.error("不好意思，您来晚啦，您的好友已完成砍价", null);
        }
        // 砍价用户身份判断
        boolean permitCut = this.permitCut(cutUserId, openId, bargain);
        if (!permitCut) {
            return Message.error("此商品仅限新注册用户帮砍", null);
        }
        ProductBargainData productBargainData = ygBargainService.findProductBargainData(bargain.getId());
        /**
         * 校验库存
         */
        if (productBargainData.getRealStock() && productBargainData.getStockQuantity().compareTo(0L) > 0) {
            int completedCount = this.findCompletedCount(productBargainData.getBargainId(), productBargainData.getProductId(), null);
            if (productBargainData.getStockQuantity() - completedCount <= 0) {
                return Message.error("亲，您来晚了，商品已被抢光。", productBargainData.getProductId());
            }
        }
        return Message.success(null);
    }

    /**
     * 砍价用户身份判断：是否只允许新注册用户砍价
     * 临时判断逻辑：砍价用户注册时间为功能上线时间之后，并且注册来源是分享用户的source，并且没有参与过任何砍价信息
     *
     * @param cutUserId
     * @param userBargain
     * @return
     */
    private boolean permitCut(Long cutUserId, String openId, YgUserBargain userBargain) {
        YgBargain bargain = ygBargainService.findById(userBargain.getBargainId());
        if (!bargain.getCutOnlyNew()) {
            return true;
        }
        if (cutUserId == null) {
            // 非注册用户
            return false;
        }
        if (cutUserId.compareTo(userBargain.getUserId()) == 0) {
            // 自己砍
            return true;
        }
        YgUser cutUser = ygUserService.findById(cutUserId);
        if (cutUser.getCreateTime().before(bargain.getStartDate())) {
            logger.info("【0元砍价用户身份判断】砍价用户注册时间不在允许值之后，cutUserId=" + cutUserId
                    + ", userBargainId=" + userBargain.getId());
            return false;
        }
        Boolean alreadyCut = ygUserBargainDetailService.alreadyCut(openId, null);
        if (alreadyCut) {
            logger.info("【0元砍价用户身份判断】砍价用户已参与过其它砍价，cutUserId=" + cutUserId
                    + ", userBargainId=" + userBargain.getId());
            return false;
        }
        return true;
    }

    private BigDecimal getThisCutPrice(YgUserBargain ygUserBargain) {
        // 获取本次砍价金额
        BigDecimal needCutPrice = ygUserBargain.getProductPrice().subtract(ygUserBargain.getTargetPrice());
        Long lastCutCount = ygUserBargain.getLastCutCount();
        Long cutCount = ygUserBargain.getCutCount();
        Long hasCutCount = cutCount - lastCutCount;
        //第一刀砍30%
        if (hasCutCount == 0 && cutCount > 1) {
            return needCutPrice.multiply(new BigDecimal("0.3"));
        }
        if (cutCount > 3 && hasCutCount <= 2) {
            if (cutCount > 6) {
                needCutPrice = needCutPrice.multiply(new BigDecimal("0.5"));
                lastCutCount = 3 - hasCutCount;
            } else {
                needCutPrice = needCutPrice.multiply(new BigDecimal("0.6"));
                lastCutCount = 3 - hasCutCount;
            }
        }
        needCutPrice = needCutPrice.subtract(ygUserBargain.getCutPrice());
        return SplitPriceUtil.splitPrice(needCutPrice.floatValue(), lastCutCount.intValue());
    }

    @Override
    public YgUserBargain findUserBargain(Long userId, Long productId, Long bargainId) {
        YgUserBargainExample example = new YgUserBargainExample();
        Criteria criteria = example.createCriteria();
        criteria.andUserIdEqualTo(userId).andProductIdEqualTo(productId).andFinishTimeGreaterThanOrEqualTo(new Date()).andStatusEqualTo(DataStatus.Valid.name())
                .andBargainStatusEqualTo(JobStatus.Running.name());
        if (bargainId != null) {
            criteria.andBargainIdEqualTo(bargainId);
        }
        List<YgUserBargain> list = ygUserBargainMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    @Override
    public List<YgShoppingCarModel> findGoodsInfoKJ(List<YgPtSkuInfo> skuList, Long userId, Long userBargainId) throws YgException {

        YgUserBargain userBargain = this.findById(userBargainId);

        if (CollectionUtils.isEmpty(skuList)) {
            YgPtSkuInfo skuInfo = new YgPtSkuInfo();
            skuInfo.setQuantity(1L);
            skuInfo.setSkuId(userBargain.getSkuId());
            skuList = Collections.singletonList(skuInfo);
        }
        List<YgShoppingCarModel> list = ygShoppingCarService.findItemInfoPt(skuList, userId);

        List<Long> skuIds = list.stream().map(YgShoppingCarModel::getSkuId).collect(Collectors.toList());
        List<YgSku> skus = ygSkuService.findByIds(skuIds.toArray(new Long[]{}));
        List<Long> arr = skus.stream().filter(sku -> !sku.getProductId().equals(userBargain.getProductId())).map(YgSku::getId).collect(Collectors.toList());
        if (arr.size() > 0) {
            throw new YgException("-1", "商品有误，" + arr.toString());
        }

        if (userBargain == null || !userBargain.getUserId().equals(userId)) {
            throw new YgException("-1", "用户尚未发起该砍价活动，userBargainId =" + userBargainId);
        }
        for (YgShoppingCarModel car : list) {
            car.setSalesPrice(userBargain.getProductPrice());
            car.setPromotionPrice(userBargain.getProductPrice().subtract(userBargain.getCutPrice()));
            car.setSalesType(PromotionType.KanJia);
        }
        return list;
    }

    @Override
    public Message commitOrderKJ(List<YgPtSkuInfo> skuList, PayType payType, Long userBargainId, Long userAddressId, BigDecimal totalPrice, String sourceCode,
                                 BigDecimal accountPrice, Long userId) throws YgException {
        CommitKjOrderParam commitKjOrderParam = new CommitKjOrderParam();
        commitKjOrderParam.setSkuId(skuList.get(0).getSkuId());
        commitKjOrderParam.setUserId(userId);
        commitKjOrderParam.setPayType(payType);
        commitKjOrderParam.setUserBargainId(userBargainId);
        commitKjOrderParam.setUserAddressId(userAddressId);
        commitKjOrderParam.setTotalPrice(totalPrice);
        commitKjOrderParam.setAccountPrice(accountPrice);
        commitKjOrderParam.setSourceCode(sourceCode);
        commitKjOrderParam.setAppType(AppType.WeChat);

        return commitOrderKJ(commitKjOrderParam);
    }

    @Override
    public Message commitOrderKJ(CommitKjOrderParam commitKjOrderParam) {
        SkuBasicData skuBasicData = ygSkuService.getBasicDataBySkuId(commitKjOrderParam.getSkuId());
        YgUserBargain userBargain = this.findUserBargain(commitKjOrderParam.getUserId(), skuBasicData.getProductId(), null);
        if (userBargain == null || !userBargain.getId().equals(commitKjOrderParam.getUserBargainId())) {
            return Message.error("您未发起该砍价活动", null);
        }
        if (!JobStatus.Running.equals(userBargain.getBargainStatus())) {
            return Message.error("请检查活动状态", null);
        }
        ProductBargainData productBargainData = ygBargainService.findProductBargainData(userBargain.getId());

        if (productBargainData.getBuyCount() > 0) {
            int completedCount = this.findCompletedCount(userBargain.getBargainId(), null, userBargain.getUserId());
            if(completedCount >= productBargainData.getBuyCount()){
                return Message.error("亲，不要贪心哦，您已经参与过该活动。", null);
            }
        }

        Boolean hasStockQuantity = hasStockQuantity(userBargain.getBargainId(), userBargain.getProductId(), productBargainData.getStockQuantity());
        if (!hasStockQuantity) {
            return Message.error("亲，您来晚了，商品已被抢光。", hasStockQuantity);
        }

        Boolean validateStockNum = ygStockService.validateStockNum(commitKjOrderParam.getSkuId(), 1L);
        if (!validateStockNum) {
            return Message.error("亲，您来晚了，商品已售罄。", validateStockNum);
        }
        Message balanceMsg = ygUserBalanceService.checkBalance(commitKjOrderParam.getAccountPrice(), commitKjOrderParam.getUserId());
        if (balanceMsg.getType().equals(Message.Type.error)) {
            return balanceMsg;
        }

        BigDecimal realTotalPrice = userBargain.getProductPrice().subtract(userBargain.getCutPrice()).add(productBargainData.getExpressPrice());

        if (realTotalPrice.compareTo(commitKjOrderParam.getTotalPrice()) != 0) {
            return Message.error("订单金额有误", realTotalPrice);
        }

        BigDecimal salePrice = userBargain.getProductPrice().subtract(userBargain.getCutPrice());
        SaveOrderBySkuDetailParam detailParam = new SaveOrderBySkuDetailParam(skuBasicData.getSkuId(), 1L, salePrice, skuBasicData.getCostPrice(), PromotionType.KanJia);

        SaveOrderBySkuParam saveOrderBySkuParam = new SaveOrderBySkuParam(userBargain.getUserId(),
                commitKjOrderParam.getUserAddressId(), commitKjOrderParam.getAppType(), commitKjOrderParam.getAccountPrice(), productBargainData.getExpressPrice(), OrderType.KanJia,
                userBargain.getId(), userBargain.getPlatformNo(), commitKjOrderParam.getFormId(), true, false, OrderStatus.WaitingPay, Collections.singletonList(detailParam));
        SaveMainOrderBo saveMainOrderBo = saveMainOrderHandler.buildOrderBySku(saveOrderBySkuParam);
        Message message = saveMainOrderHandler.saveMainOrder(saveMainOrderBo);
        if (Message.isSuccess(message)) {
            autoCompleteUserBargain(userBargain.getId(), true);
        }
        return message;
    }


    @Override
    public Message sendCutMsg(String cutName, BigDecimal cutPrice, String to, Long userBargainId, String platformNo) {
        if (StringUtil.isNotBlank(platformNo)) {
            UserBargainInfo userBargainInfo = findUserBargainInfo(userBargainId);

            BigDecimal currentPrice = userBargainInfo.getProductPrice().subtract(userBargainInfo.getCutPrice());
            String currentPriceStr = currentPrice.doubleValue() + "元";
            String[] keywords;
            WxMessageType wxMessageType;
            if (Constant.YIJIADIAN_PLATFORM_NO.equals(platformNo)) {
                String url = "pages/bargain/detail/detail?userBargainId=" + userBargainId;
                if (currentPrice.compareTo(userBargainInfo.getTargetPrice()) == 0) {
                    wxMessageType = WxMessageType.BargainSuccessYJD;
                    BigDecimal targetPrice = userBargainInfo.getTargetPrice();
                    String targetPriceStr = targetPrice.doubleValue() + "";
                    String content = "您的目标价格已达成，赶快去购买吧！";
                    keywords = new String[]{targetPriceStr, userBargainInfo.getProductName(), "已成功", content};
                } else {
                    String process = "已砍价 " + userBargainInfo.getCutPrice() + "元";
                    String diffString = DateConvertUtils.diffString(new Date(), userBargainInfo.getFinishTime());

                    String content = cutName + "帮您砍了" + cutPrice + "元，恭喜您离目标又进了一步！";
                    keywords = new String[]{userBargainInfo.getProductName(), process, diffString, content, currentPriceStr};
                    wxMessageType = WxMessageType.BargainProgressYJD;
                }
                wxSmallMessageService.sendTempMessage(wxMessageType, to, url, keywords);
            } else {
                return Message.error("尚未开通此模板", "");
            }
        }
        return Message.success(null);

    }

    @Override
    public Message sendCutMsg(String cutName, BigDecimal cutPrice, String to, Long userBargainId) {
        executorService.execute(() -> {

            Boolean isCom = isBargainCompletion(userBargainId);
            String url = "http://m.yiigoo.com/bargain/details.html?sourcePage=my&bargainId=" + userBargainId;
            String msg = "<a href='" + url + "'>" + cutName + "帮您砍了" + cutPrice + "元，剁手路上麻麻们互帮互助，越走越远！</a>";
            if (isCom) {
                msg = "<a href='" + url + "'>您的目标价格已达成，麻麻剁手委员会发来剁手邀请，赶快去剁手吧！</a>";
            }
            Text text = new Text(msg);
            wxMpMessageService.sendCustomMsg(text, to);
        });

        return Message.success(null);
    }

    @Override
    public Boolean isBargainCompletion(Long userBargainId) {
        YgUserBargain userBargain = ygUserBargainMapper.selectByPrimaryKey(userBargainId);
        return isBargainCompletion(userBargain);
    }

    private Boolean isBargainCompletion(YgUserBargain userBargain) {
        if (userBargain == null || userBargain.getCutPrice() == null) {
            return false;
        }
        BigDecimal lastPrice = userBargain.getProductPrice().subtract(userBargain.getCutPrice());
        return lastPrice.compareTo(userBargain.getTargetPrice()) == 0 || JobStatus.Complete.equals(userBargain.getBargainStatus());
    }


    @Override
    public List<YgUserBargain> findUserBargainLastOneHour(Date startTime, Date endTime) {
        startTime = DateConvertUtils.addMinute(startTime, 60);
        endTime = DateConvertUtils.addMinute(endTime, 60);
        YgUserBargainExample example = new YgUserBargainExample();
        example.createCriteria().andFinishTimeLessThanOrEqualTo(endTime).andStatusEqualTo(DataStatus.Valid.name()).andFinishTimeGreaterThan(startTime)
                .andBargainStatusNotEqualTo(JobStatus.Complete.name());
        return ygUserBargainMapper.selectByExample(example);
    }

    @Override
    public void sendBargainInvitation(Long userBargainId) {
        YgUserBargain userBargain = this.findById(userBargainId);
        if (Constant.YIJIADIAN_PLATFORM_NO.equals(userBargain.getPlatformNo())) {
            YgUserAuths userAuths = ygUserAuthsService.findByUserId(userBargain.getUserId(), 1L);
            if (userAuths == null) {
                return;
            }
            WxAttention wxAttention = wxAttentionService.findByOpenId(userAuths.getOpenId());
            if (wxAttention == null) {
                return;
            }
            String url = "pages/bargain/detail/detail?userBargainId=" + userBargainId;
            String process = "已砍价 " + userBargain.getCutPrice() + "元";
            String diffString = DateConvertUtils.diffString(new Date(), userBargain.getFinishTime());

            BigDecimal currentPrice = userBargain.getProductPrice().subtract(userBargain.getCutPrice());
            String currentPriceStr = currentPrice.doubleValue() + "元";
            String content = "剁手活动还有1小时就要结束啦，邀请更多小伙伴帮你砍价吧！";
            String[] keywords = new String[]{userBargain.getProductName(), process, diffString, content, currentPriceStr};
            wxSmallMessageService.sendTempMessage(WxMessageType.BargainProgressYJD, userAuths.getOpenId(), url, keywords);
        }
    }

    @Override
    public int updateBargainExpiredStatus(Long userBargainId) {
        YgUserBargain userBargain = this.findById(userBargainId);
        if (JobStatus.Finish.equals(userBargain.getBargainStatus())) {
            userBargain.setBargainStatus(JobStatus.Finish);
            userBargain.setUpdateTime(new Date());
            return ygUserBargainMapper.updateByPrimaryKeySelective(userBargain);
        }
        return 0;
    }

    @Override
    public int findCompletedCount(Long bargainId, Long productId, Long userId) {
        Assert.notNull(bargainId, "bargainId can't be null");
        YgUserBargainExample example = new YgUserBargainExample();
        Criteria criteria = example.createCriteria().andBargainIdEqualTo(bargainId);
        if (userId != null) {
            criteria.andUserIdEqualTo(userId);
        }
        if (productId != null) {
            criteria.andProductIdEqualTo(productId);
        }
        criteria.andBargainStatusEqualTo(JobStatus.Complete.name()).andStatusEqualTo(DataStatus.Valid.name());
        return ygUserBargainMapper.countByExample(example);
    }

    @Override
    public Map<String, Object> findItemInfo(List<YgPtSkuInfo> skuList, Long userId, Long userBargainId) {

        List<YgShoppingCarModel> list = this.findGoodsInfoKJ(skuList, userId, userBargainId);
        Map<String, Object> map = new HashMap<>();
        BigDecimal productPrice = new BigDecimal("0.00");
        BigDecimal specialPrice = new BigDecimal("0.00");
        for (YgShoppingCarModel model : list) {
            productPrice = productPrice.add(model.getPromotionPrice().multiply(new BigDecimal(model.getQuantity())));
        }
        List<List<YgShoppingCarModel>> sortCarList = ygShoppingCarService.sortCarList(list, userId);
        ProductBargainData productBargainData = ygBargainService.findProductBargainData(userBargainId);
        YgUserBargain userBargain = findById(userBargainId);
        map.put("carList", sortCarList);
        map.put("productPrice", productPrice);
        map.put("specialPrice", specialPrice);
        map.put("userAddressId", userBargain.getUserAddressId());
        map.put("expressPrice", productBargainData.getExpressPrice());
        return map;
    }

    @Autowired
    private YgCardCouponDetailService ygCardCouponDetailService;
    @Autowired
    private YgCardCouponService ygCardCouponService;
    @Autowired
    private SaveMainOrderHandler saveMainOrderHandler;

    @Transactional(propagation = Propagation.NOT_SUPPORTED, rollbackFor = Exception.class)
    public void autoCompleteUserBargain(Long userBargainId, Boolean buyNow) {
        YgUserBargain userBargain = ygUserBargainMapper.selectByPrimaryKey(userBargainId);
        ProductBargainData productBargainData = ygBargainService.findProductBargainData(userBargain.getProductId(),
                userBargain.getBargainId(), userBargain.getPlatformNo());
        if (!buyNow) {
            Boolean bargainCompletion = isBargainCompletion(userBargain);
            if (!bargainCompletion) {
                return;
            }
        }
        BargainGenerationMode generationMode = buyNow ? BargainGenerationMode.Order : BargainGenerationMode.valueOf(productBargainData.getGenerationMode());
        //回写完成状态
        int updateUserBargainStatusComplete = this.updateUserBargainStatusComplete(userBargainId, generationMode);
        closeOtherUserBargain(productBargainData);
        if (updateUserBargainStatusComplete != 1) {
            logger.warn("用户砍价生成" + productBargainData.getGenerationMode() + "失败;砍价状态为完成。userBargainId =" + userBargainId);
            return;
        }
        if (!buyNow) {
            Long skuId = getSkuId(userBargain);
            SkuBasicData skuBasicData = ygSkuService.getBasicDataBySkuId(skuId);
            if (BargainGenerationMode.CardCoupon.name().equals(productBargainData.getGenerationMode())) {
                YgCardCoupon cardCoupon = ygCardCouponService.findById(83L);
                cardCoupon.setSkuId(skuId);
                cardCoupon.setCardCountDown(productBargainData.getCardCountDown());
                cardCoupon.setProductIds(skuBasicData.getProductId().toString());
                ygCardCouponDetailService.generateCardCoupon(userBargain.getUserId(), cardCoupon, null, "", "");
            } else {
                AppType appType = getAppType(userBargain.getPlatformNo());

                BigDecimal totalPrice = userBargain.getTargetPrice().add(productBargainData.getExpressPrice());
                OrderStatus orderStatus = totalPrice.compareTo(BigDecimal.ZERO) == 0 ? OrderStatus.WaitingSend : OrderStatus.WaitingPay;
                SaveOrderBySkuDetailParam detailParam = new SaveOrderBySkuDetailParam(skuBasicData.getSkuId(), 1L, userBargain.getTargetPrice(), skuBasicData.getCostPrice(), PromotionType.KanJia);
                SaveOrderBySkuParam saveOrderBySkuParam = new SaveOrderBySkuParam(userBargain.getUserId(), userBargain.getUserAddressId(),
                        appType, BigDecimal.ZERO, productBargainData.getExpressPrice(), OrderType.KanJia, userBargain.getId(), userBargain.getPlatformNo(),
                        null, true, false, orderStatus, Collections.singletonList(detailParam));
                SaveMainOrderBo saveMainOrderBo = saveMainOrderHandler.buildOrderBySku(saveOrderBySkuParam);
                saveMainOrderHandler.saveMainOrder(saveMainOrderBo);
            }

            YgUser user = ygUserService.findById(userBargain.getUserId());
            sendSmsMsg(JobStatus.Complete, BargainGenerationMode.valueOf(productBargainData.getGenerationMode()), Collections.singletonList(user.getTelPhone()));

        }

    }

    @Autowired
    private SmsService smsService;

    private void sendSmsMsg(JobStatus bargainStatus, BargainGenerationMode generationMode, List<String> phoneList) {
        executorService.execute(() -> {
            String msg = null;
            if (JobStatus.Complete.equals(bargainStatus)) {
                //发给成功人
                if (BargainGenerationMode.Order.equals(generationMode)) {
                    msg = "您的砍价已生成待付款订单,请登录壹家店小程序进行付款。";
                } else {
                    msg = "您的砍价商品已生成卡券,请登录壹家店小程序下单带走吧。";
                }
            } else if (JobStatus.Finish.equals(bargainStatus)) {
                //发给关闭的人
                msg = "您发起的砍价商品，因库存不足，进行中的活动系统已取消，请您谅解。";
            }
            if (StringUtil.isNotBlank(msg)) {
                logger.info("bargain.sendSmsMsg->msg = 【{}】, phone=【{}】", msg, JSON.toJSONString(phoneList));
                for (String phone : phoneList) {
                    smsService.sendSms(phone, msg);
                }
            }
        });

    }


    private void closeOtherUserBargain(ProductBargainData productBargainData) {
        Boolean realStock = productBargainData.getRealStock();
        if (realStock) {
            int completedCount = this.findCompletedCount(productBargainData.getBargainId(), productBargainData.getProductId(), null);
            long lastCount = productBargainData.getStockQuantity() - completedCount;
            if (lastCount <= 0) {
                List<String> userPhoneList = getUserPhoneList(productBargainData.getBargainId(), productBargainData.getProductId(), JobStatus.Running);
                this.closeRunningUserBargain(productBargainData.getBargainId(), productBargainData.getProductId(), "system", new Date());
                sendSmsMsg(JobStatus.Finish, BargainGenerationMode.valueOf(productBargainData.getGenerationMode()), userPhoneList);

            }
        }
    }

    private List<String> getUserPhoneList(Long bargainId, Long productId, JobStatus bargainStatus) {
        return ygUserBargainMapper.getUserPhoneList(bargainId, productId, bargainStatus);
    }

    @Override
    public int closeRunningUserBargain(Long bargainId, Long productId, String remark, Date updateTime) {
        return ygUserBargainMapper.updateRunningUserBargainStatusFinish(bargainId, productId, remark, updateTime);
    }

    @Override
    public int updateUserBargainStatusComplete(Long userBargainId, BargainGenerationMode generationMode) {
        return ygUserBargainMapper.updateUserBargainStatusComplete(userBargainId, generationMode);
    }

    private AppType getAppType(String platformNo) {
        if (Constant.YIJIADIAN_PLATFORM_NO.equals(platformNo)) {
            return AppType.Small;
        } else {
            return AppType.WeChat;
        }
    }

    private Long getSkuId(YgUserBargain userBargain) {
        Long skuId = userBargain.getSkuId();
        if (skuId == null) {
            List<YgSku> stockList = ygStockService.findByProductId(userBargain.getProductId());
            skuId = stockList.stream().max((o1, o2) -> {
                Long amount1 = o1.getStock().getAmount();
                Long amount2 = o2.getStock().getAmount();
                return amount1.compareTo(amount2);
            }).get().getId();

        }
        return skuId;
    }

    /**
     * 砍价商品还有库存剩余量
     * <p>
     * 花色级别
     *
     * @param bargainId           砍价活动id
     * @param productId           商品id
     * @param sourceStockQuantity 活动设置库存量
     * @return Boolean
     */
    private Boolean hasStockQuantity(Long bargainId, Long productId, Long sourceStockQuantity) {
        int completedCount = this.findCompletedCount(bargainId, productId, null);
        return sourceStockQuantity - completedCount > 0;
    }


}
